package comm.net.svr;

import comm.net.protocol.Protocol;
import comm.net.protocol.Protobuf;
import comm.utill.Errno;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;

public class Server {
	private int port;

	public Server(int port) {
		this.port = port;
	}

	public void run() {
	    final Server server = this;
		EventLoopGroup bossGroup = new NioEventLoopGroup(1); 				 // 用于处理服务器端接收客户端连接
		EventLoopGroup workerGroup = new NioEventLoopGroup(30); 			 // 进行网络通信（读写）
		ServerBootstrap bootstrap = new ServerBootstrap();					 // 辅助工具类，用于服务器通道的一系列配置

		try {
			bootstrap.group(bossGroup, workerGroup) 						 // 绑定两个线程组
					.channel(NioServerSocketChannel.class)					 // 指定NIO类型的channel
					.childHandler(new ChannelInitializer<SocketChannel>() {  // 配置具体的数据处理方式（有连接到达时会创建一个channel）
						@Override
						protected void initChannel(SocketChannel socketChannel) throws Exception {

                            // decoded
                            socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                            //解码客户端发过来的消息
                            socketChannel.pipeline().addLast(new ProtobufDecoder(Protobuf.Pro.getDefaultInstance()));
                            // encoded
                            socketChannel.pipeline().addLast(new LengthFieldPrepender(4));
                            socketChannel.pipeline().addLast(new ProtobufEncoder());

							// pipeline管理channel中的Handler，在channel队列中添加一个handler来处理业务
							socketChannel.pipeline().addLast(new ServerHandler(server));
						}
					}).option(ChannelOption.SO_BACKLOG, 128) 		        // 设置TCP缓冲区
					.option(ChannelOption.SO_SNDBUF, 32 * 1024) 	        // 设置发送数据缓冲大小
					.option(ChannelOption.SO_RCVBUF, 32 * 1024) 	        // 设置接受数据缓冲大小
					.childOption(ChannelOption.SO_KEEPALIVE, true);         // 保持连接

			ChannelFuture future = bootstrap.bind("127.0.0.1", port).sync(); 				// 配置完成，开始绑定server，通过调用sync同步方法阻塞直到绑定成功

			System.out.println("启动"+ server.getClass().getName() +" 监听： " + future.channel().localAddress());

			// 应用程序会一直等待，直到channel关闭
			future.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}

	public int processMethod(Protocol recvProtocol, Protocol sendProtocol) {
        int rt = Errno.ARGS_ERROR;
        return rt;
    }
}
